/*
   程序的目的：测试进程间的通信
*/
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <cerrno>  //包含errno变量的头文件
#include <assert.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
    //1.创建管道
     int pipefd[2] = {0}; //创建管道描述符的数组
     int n = pipe(pipefd); //创建管道
     if(n < 0) //管道创建失败
     {
        std::cout<<"pipe error:"<<errno<<" "<<strerror(errno)<<std::endl;
        return 1;
     }
     //查看读写端的文件描述符
     std::cout<<"pipefd[0]："<<pipefd[0]<<std::endl;   //0读取端--》嘴巴--》读书
     std::cout<<"pipefd[1]："<<pipefd[1]<<std::endl;   //1写入端--》笔--》写东西

    //2.创建子进程
     pid_t id = fork(); //断言：意料之中用assert，意料之外用if
     //assert(id < 0);  //这个虽然意料之外，但我们用assert
    if(id < 0)  //子进程创建失败
    {
        std::cout<<"id error:"<<errno<<" "<<strerror(errno)<<std::endl;
        return 1;
    }
    if(id == 0) //子进程
    {
      //3.关闭不需要的fd-->父进程读取数据，子进程写入数据
        close(pipefd[0]); //关闭读取端
         //4.开始通信
        //开始向管道写入数据
        // const char* namstr = "hello,我是子进程";
        // int cnt = 1;
        // char buffer[1024];
        int cnt = 0;
        while(true)  //持续写入
        {
            char x = 'X';
            std::cout<<"Cnt："<<cnt++<<std::endl;
            sleep(1);
            write(pipefd[1],&x,1);
          //snprintf(buffer,sizeof buffer,"%s：my pid：%d,计数器：%d",namstr,getpid(),cnt++);
          //write(pipefd[1],buffer,strlen(buffer));
          //sleep(1);
          //sleep(10);
          //sleep(3);
          //break;
        }
        //写完之后，关闭写入端
        close(pipefd[1]);
        exit(0);
    }
    //3.关闭不需要的fd-->父进程读取数据，子进程写入数据
     //父进程
     close(pipefd[1]); //关闭写入端
    //4.开始通信
    char buffer[1024];
    int cnt = 0;
    //不断读取
    while(true)
    {
       //sleep(1);
       //sleep(10);
       int n = read(pipefd[0],buffer,sizeof(buffer) -1); //细节：读取减一，因为read是字节流读取，不是字符串类型读取
       if(n > 0)
       {
        buffer[n] = '\0'; //留一个字节空间补'\0'
        std::cout<<"我是父进程，child give me massage："<<buffer<<std::endl;
       }else if(n == 0)
       {
        std::cout<<"我是父进程，我读到文件的末尾"<<std::endl;
        break;
       }else
       {
        std::cout<<"我是父进程，读取异常"<<std::endl;
        break;
       }
       //sleep(1);
       if(cnt++ > 5) break;
    }
    //读完之后，关闭读取端
    close(pipefd[0]);
    int status = 0;
    waitpid(id,&status,0);
    std::cout<<"sig："<<(status&0x7F)<<std::endl;
    return 0;
}
